/* improve_div_main.c */

#include "../common/improve_div.h"

#ifdef MTRACE
#include <mcheck.h>
#endif

int main(int argc, char** argv)
{
	int result = 0, n = 0, i = 0, g1_size = 0, g2_size = 0;
	int return_value = 1, elements_no = 0, old_g1_length = 0;
	int *g = NULL, *old_g1 = NULL, *g1 = NULL, *g2 = NULL;
	sparse_matrix_lst* A = NULL;
	elem *s = NULL, *k = NULL, *k_g = NULL, delta_Q = 0, vec_mat_vec_res = 0;
	elem **B = NULL, **B_g = NULL , *f = NULL, *res_vec = NULL, M = 0;

	if (argc != 4)
	{
		result = printf("\n usage: improve_div <adjacency-mat-file>"
						" <group-file> <first-subgroup-file>\n");
		assert(result >= 0);
		return -1;
	}

	#ifdef MTRACE
	mtrace(); /* Starts the recording of memory allocations and releases */
   	#endif
   
	A = read_adjacency_matrix(argv[1]);
	if (A == NULL)
	{
		return_value = -1;
		goto main_cleanup;
	}

    n = A->n ;
	g = (int*)calloc(n, sizeof(int));
	assert(g != NULL);

	elements_no = read_group_file(argv[2], g);

	old_g1 = (int*)calloc(n, sizeof(int));
	assert(old_g1 != NULL);

	old_g1_length = read_group_file(argv[3], old_g1);

	if (elements_no == -1)
	{
		return_value = -1;
		goto main_cleanup;
	}

	B = create_modularity_mat(A);
	/*	Sending a zeroed f so that the matrix is a sub matrix of B
		and not generalized  */
	f = (elem*)calloc(elements_no, sizeof(elem));
	B_g = create_generalized_modularity_matrix(B, g, elements_no, f, n);
	
	s = (elem*) calloc(elements_no, sizeof(elem));
	assert(s != NULL);

	k = calc_nodes_degrees(A);
	M = count_edges(k, A->n);

	k_g = create_k_g(k, g, elements_no);

	create_s(g, old_g1, s, elements_no, old_g1_length);
	
	delta_Q = improve_2_div(B_g, s, k_g, M, elements_no);

	div_indices(s, g, &g1, &g2, &g1_size, &g2_size, elements_no);

	printf("%lf\n", delta_Q);

	print_groups(g1, g2, g1_size, g2_size);


main_cleanup:
	if (B_g != NULL)
		free_matrix(B_g, elements_no);
	if (A != NULL)
		free_sparse_matrix_lst(A);
	if (g != NULL)
		free(g);
	if (B != NULL)
		free_matrix(B, n);
	if (f != NULL)
		free(f);
	if (g1 != NULL)
		free(g1);
	if (s != NULL)
		free(s);
	if (k != NULL)
		free(k);
	if (k_g != NULL)
		free(k_g);
	if (old_g1 != NULL)
		free(old_g1);

	#ifdef MTRACE
     /* End of memory allocation checks. */
     muntrace();
	#endif
	return return_value;
}
